﻿using Csla;
using Csla.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using Csla.Security;
using System.Data.SqlClient;
using lite;
using OpenExpressApp.ORM;
using OpenExpressApp.DB.Utils;

namespace OpenExpressApp.Module.Library.Security
{
    /// <summary>
    /// 注意：防止重名，User增加Code区分唯一性，查询时通过Code查询，同时返回Code和Name
    /// </summary>
    [Serializable()]
    public class OEAIdentity : CslaIdentity
    {
        [NotUndoable]
        //[NonSerialized]
        private OrgPositions _roles;

        #region  Factory Methods

        internal static OEAIdentity GetIdentity(string username, string password)
        {
            return DataPortal.Fetch<OEAIdentity>(new UsernameCriteria(username, password));
        }

        public User User { get; set; }

        private OEAIdentity()
        { /* require use of factory methods */ }

        #endregion

        #region  Data Access

        public new OrgPositions Roles
        {
            get
            {
                return this._roles;
            }
            private set
            {
                this._roles = value;
            }
        }

        /// <summary>
        /// 是否参数代表部门或者它的上级部门
        /// </summary>
        /// <param name="orgId"></param>
        /// <returns></returns>
        public bool HavePermissionOnOrg(Guid orgId)
        {
            return -1 != OrgsHavePermission.IndexOf(orgId);
        }

        [NonSerialized]
        private IList<Guid> _orgsHavePermission;
        private IList<Guid> OrgsHavePermission
        {
            get
            {
                //缓存拥有权限的部门
                if (null == _orgsHavePermission)
                {
                    _orgsHavePermission = new List<Guid>();
                    using (var db = DBHelper.CreateDb(ConnectionStringNames.OpenExpressApp))
                    {
                        foreach (OrgPosition item in _roles)
                        {
                            string sql = string.Format(@"
                            with orgt
                            as
                            (
	                            select * from Org where Id = '{0}'
	                            union all 
	                            select Org.* from orgt inner join Org on Org.Pid = orgt.Id
                            )

                            select * from orgt
                            ", item.OrgId);
                            var orgs = db.Exec(typeof(Org), "sys.sp_sqlexec", new object[] { sql });
                            foreach (Org org in orgs)
                                _orgsHavePermission.Add(org.Id);
                        }
                    }
                }
                return _orgsHavePermission;
            }
        }

        public bool HavePermissionOnOperation(Guid businessObjectId, Guid operationId)
        {
            bool result = false;
            foreach (var item in Roles)
            {
                result = result || item.OrgPositionOperations.HavePermissionOnOperation(businessObjectId, operationId);
                if (result) break;
            }
            return result;
        }

        public string[] GetDataPermissionExpr(Guid businessObjectId)
        {
            string[] exprs = new string[Roles.Count];
            int index = 0;
            foreach (var role in Roles)
            {

                var items = role.OrgPositionDataPermissions.Where<OrgPositionDataPermission>(x => x.BusinessObjectId == businessObjectId);
                exprs[index] = String.Empty;
                foreach (var item in items)
                {
                    if (String.Empty != item.Expression)
                        exprs[index] = exprs[index] + "And" + item.Expression;
                }
                if (!String.IsNullOrEmpty(exprs[index]))
                {
                    exprs[index] = exprs[index].Substring("And".Length);
                }
                index++;
            }
            string[] result = new string[index];
            index = 0;
            foreach(var expr in exprs)
            {
                if (!String.IsNullOrEmpty(expr))
                {
                    result[index] = expr;
                    index++;
                }
            }
            Array.Resize<string>(ref result, index);
            return result;
        }

        private void DataPortal_Fetch(UsernameCriteria criteria)
        {
            User = UserList.Get(criteria.Username, criteria.Password);

            if (null != User)
            {
                base.Name = User.Name;
                base.IsAuthenticated = true;
                _roles = OrgPositions.GetList(User.Id); // list of roles from security store
            }
            else
            {
                base.Name = string.Empty;
                base.IsAuthenticated = false;
                _roles = null;
            }
        }

        //private void Fetch(User user)
        //{
        //  if (user != null)
        //  {
        //    Name = user.Username;
        //    IsAuthenticated = true;
        //    var roleList = new Csla.Core.MobileList<string>();
        //    var roles = from r in user.Roles select r;
        //    foreach (var role in roles)
        //      roleList.Add(role.Role1);
        //    Roles = roleList;
        //  }
        //  else
        //  {
        //    Name = "";
        //    IsAuthenticated = false;
        //    Roles = new Csla.Core.MobileList<string>();
        //  }
        //}

        #endregion

    }
}
